import React, { useEffect, useState } from 'react'
// @ts-expect-error 解决报错
import * as THREE from 'three'
// @ts-expect-error 解决报错
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import ReactPlayer from 'react-player'
// @ts-expect-error 解决报错
import scene_collision from '../../../public/scene_collision.glb'
// @ts-expect-error 解决报错
import scene_desk_obj from '../../../public/scene_desk_obj.glb'
// @ts-expect-error 解决报错
import { Capsule } from 'three/examples/jsm/math/Capsule.js'
// @ts-expect-error 解决报错
import { Octree } from 'three/examples/jsm/math/Octree.js'
// @ts-expect-error 解决报错
import { OctreeHelper } from 'three/examples/jsm/helpers/OctreeHelper.js'
import './index.css'

const Index: React.FC = () => {
  // controls
  const [keyStates, setKeyStates] = useState({}) // { keyW:true }

  const worldOctree = new Octree()

  const GRAVITY = 30

  // player
  const player = {
    geomotry: new Capsule(
      new THREE.Vector3(0, 0.35, 0),
      new THREE.Vector3(0, 6, 0),
      1.5
    ),
    velocity: new THREE.Vector3(),
    direction: new THREE.Vector3(),
    onFloor: false
  }

  const [info, setInfo] = useState<string | null>(null)
  const [introduction, setIntroduction] = useState<string | null>(null)
  const [title, setTitle] = useState<string | null>(null)
  let time: null | number = null

  // 图片
  const [image] = useState([
    {
      url: '/src/assets/image/1.png',
      title: '美女1',
      author: '',
      describe: `这张图片成功地捕捉到了一位年轻女性的静态美，她坐在室内，身穿绿色连帽衫和蓝白相间的格子裤，显得既休闲又不失时尚感。她的黑色披肩长发与整体造型相得益彰，更添一份柔美。女性的表情平静而自然，看向镜头的眼神中透露出一种淡然与自信。她的一只手托着下巴，展现出一种思考或放松的姿态，而另一只手则安静地放在大腿上，整个姿势显得既优雅又舒适。背景中的白色沙发和装饰品为整个场景增添了一份温馨与舒适感。花瓶里的花朵更是点睛之笔，不仅提升了空间的生气与活力，还与女性的青春气质相呼应。总的来说，这张图片通过细腻的构图和色彩搭配，成功地传达了一种温馨、舒适、自然的氛围，同时也展现了女性的美丽与自信。这样的图片很容易引起观众的共鸣，让人感受到一种内心的平静与满足。`
    },
    {
      url: '/src/assets/image/2.png',
      title: '美女2',
      author: '',
      describe: `这位年轻女性给人一种温婉、优雅的感觉。她身穿绿色连帽衫，显得休闲而又不失时尚感。黑色的长发与白皙的皮肤形成了鲜明的对比，更凸显出她的青春活力。她的大眼睛有神且充满好奇，仿佛在通过手机探索着未知的世界。背景中的一束花和一些装饰品为整个场景增添了一份温馨与浪漫。这些元素不仅提升了空间的生气与活力，还与女性的气质相呼应，共同营造出一个舒适宜人的环境。整体而言，这张图片通过细腻的构图和色彩搭配，成功地传达了一种温馨、舒适、浪漫的氛围。女性的形象与背景环境相得益彰，共同构成了一幅和谐美好的画面。这样的图片很容易引起观众的共鸣，让人感受到一种内心的平静与满足。`
    },
    {
      url: '/src/assets/image/3.png',
      title: '美女3',
      author: '',
      describe: `这位年轻女性展现出了积极向上的态度和亲和力。她身着的绿色连帽衫不仅颜色鲜亮，而且上面的蓝色图案为整体装扮增添了活泼感。她的黑色长发显得自然柔顺，棕色的眼睛闪烁着温暖的光芒，加上她那真诚的微笑，都让人感受到她的友善与乐观。她右手竖起大拇指的动作，无疑是在表达一种积极的情绪或是对某事的高度认可，这种正面的肢体语言很容易感染到周围的人，传递出正能量。背景虽然模糊，但室内环境的设定和温馨的色调都让人感受到家的温暖与舒适。这种模糊处理不仅突出了人物主体，还留给了观众一定的想象空间。`
    },
    {
      url: '/src/assets/image/4.png',
      title: '美女4',
      author: '',
      describe: `这位年轻女性展现出了自信、积极且充满活力的形象。她身着的绿色连帽衫不仅颜色鲜亮，而且上面的蓝色字母“X”为整体装扮增添了时尚感。她的黑色长发披肩，显得自然且富有光泽，与她的棕色大眼睛相得益彰，共同构成了她美丽的面容。她涂了红色口红，脸颊微红，这种妆容不仅突出了她的五官，还给人一种健康、有活力的感觉。她的微笑温暖而真诚，竖起的大拇指则传达出积极的情绪或是对某事的赞同，这种正面的肢体语言很容易感染到周围的人。尽管背景模糊不清，但室内环境的设定和整体的色调都让人感受到一种轻松愉快的氛围。这种氛围与年轻女性的形象相得益彰，共同构成了一张充满正能量的照片。`
    },
    {
      url: '/src/assets/image/5.png',
      title: '美女5',
      author: '',
      describe: `这位年轻女性给人一种简约而不失时尚的感觉。她身着的绿色连帽衫与白色T恤的搭配，既休闲又舒适，同时也不失为一种流行的穿搭方式。T恤上的“COSMOPOLITAN”字样可能暗示着她对时尚和流行的敏感，或者是她个人品味的一种体现。她的黑色长发自然垂落，刘海微微遮住额头，给人一种温柔且知性的感觉。细长的项链和心形吊坠则为整体装扮增添了一丝精致感，这种细节上的处理往往能够体现一个人的品味和用心。她的右手拿着连帽衫的帽子，左手放在膝盖上，这种坐姿显得轻松自然，没有过多的造作或僵硬。她的眼神看向镜头，脸上带着微笑，这种自信和亲和力很容易感染到周围的人。背景是一个简单的房间，墙壁为白色，没有其他显著物品或装饰，这种简约的背景更能够突出人物主体，让观众更加专注于她的形象和气质。`
    },
    {
      url: '/src/assets/image/6.png',
      title: '美女6',
      author: '',
      describe: `这位年轻女性展现出了自信、活泼且亲和力十足的形象。她身着的白色T恤上的绿色和红色图案为整体装扮增添了活力与时尚感，尽管品牌标志不太清晰，但这并不妨碍她整体形象的展现。她的黑色长发与刘海的搭配，显得既自然又青春，与她的年轻气质相得益彰。她的眼睛看向镜头，脸上洋溢着真诚的微笑，这种自信的表现很容易感染到周围的人，让人感受到她的热情和友好。她的双手做出的“V”字形手势，不仅传达出胜利或和平的积极信息，还增添了一份俏皮与可爱。背景是一个简单的室内环境，但正是这种简约而不失温馨的氛围，更加凸显了人物的主体地位，让观众能够更加专注于她的形象和气质。半开的门和模糊的家具背景，为整体画面增添了一丝神秘感，让人不禁想要探究门后的世界。`
    },
    {
      url: '/src/assets/image/shidiqi.png',
      title: '动漫1',
      author: '',
      describe: `这张图片确实展现了一个非常有趣和生动的卡通角色。角色的设计非常吸引人，特别是它的大眼睛和尖耳朵，给人一种可爱和机灵的感觉。蓝色的配色方案也很成功，使得整个角色看起来更加鲜明和引人注目。此外，角色开心和友好的表情也增加了整个图像的趣味性。它的嘴巴张开露出了牙齿，仿佛在笑，这样的表情很容易引发观众的共鸣和喜爱。而角色从一张纸或材料中撕裂出来的设计也非常独特和有趣，给人一种活泼和幽默的感觉。背景虽然简单，但浅蓝色的选择却恰到好处地衬托出了角色的形象，使得整个画面看起来更加和谐统一。`
    },
    {
      url: '/src/assets/image/shidiqi1.png',
      title: '动漫2',
      author: '',
      describe: `这张图片展示了一只蓝色卡通动物在沙滩上弹吉他的画面，整体设计充满了创意和趣味性。动物的造型非常独特，大眼睛、尖耳朵以及穿着白色衬衫和蓝色手套的装扮都让它看起来非常可爱和引人注目。特别是它戴着的蓝色帽子，与整体的蓝色调非常协调，增添了更多的活泼感。背景的设计也非常成功，晴朗的天空和海洋、海面上的白云以及沙滩上的粉红色花瓣都营造出一种轻松愉快的氛围。这种氛围与动物弹吉他的场景相得益彰，使得整个画面更加生动有趣。此外，图片的色彩搭配也非常出色，蓝色和白色的运用使得整体色调清新明快，给人一种清爽的感觉。而粉红色花瓣的点缀则增加了画面的柔和度和温馨感，使得整个画面更加和谐美好。`
    },
    {
      url: '/src/assets/image/shidiqi2.png',
      title: '动漫3',
      author: '',
      describe: `这只蓝色外星生物的设计非常独特且引人注目。它的大眼睛、尖耳朵和尾巴等外星特征赋予了它鲜明的个性和特点，使其在众多卡通或科幻形象中脱颖而出。同时，它的表情似乎有些困惑或不悦，这种情绪的表达也为它增添了更多的生动性和趣味性。穿着白色浴袍和帽子的造型给人一种休闲而又不失庄重的感觉，金色的边缘和徽章则提升了整体的质感。特别是帽子上的黄色小球装饰，不仅与整体色调相协调，还为整体形象增添了一丝活泼和可爱。此外，这只生物的手指伸出来，好像在做停止的手势，这种姿态和动作的设计也非常巧妙，既符合外星生物的神秘和未知感，又增加了与观众的互动性和趣味性。背景虽然纯色且没有其他元素，但这种简洁的处理方式却更加凸显了外星生物的形象和特点，使其更加突出和鲜明。`
    },
    {
      url: '/src/assets/image/shidiqi3.png',
      title: '动漫4',
      author: '',
      describe: `这张图片成功地捕捉到了动画片《Lilo & Stitch》中角色的独特魅力和个性。蓝色的卡通动物形象生动可爱，嘴巴大张着的表情仿佛在笑或者说话，这种活泼有趣的姿态很容易吸引观众的注意力。黑色的眼睛和粉红色的鼻子等细节处理也非常到位，使得整个角色更加立体和生动。背景虽然模糊，但恰好为角色提供了一个温馨而舒适的室内环境。这种环境氛围与角色轻松愉快的表情相得益彰，使得整个场景更加和谐美好。左下角的饮料杯和柠檬片则增添了一些生活气息和细节感，让整个画面更加生动有趣。此外，这张图片的色彩搭配也非常出色。蓝色的角色与背景中的暖色调形成了鲜明的对比，使得角色更加突出和鲜明。同时，整体色调也给人一种轻松愉快的感觉，与图片所要传达的氛围非常契合。`
    }
  ])

  useEffect(() => {
    // 获取元素
    const can = document.getElementById('can')
    const clock = new THREE.Clock()
    // 创建场景
    const scene = new THREE.Scene()
    // 位置
    scene.position.y = -7
    // scene.position.z = 4

    // 创建相机
    const camera = new THREE.PerspectiveCamera(
      70,
      window.innerWidth / window.innerHeight,
      0.01,
      1000
    )
    camera.position.set(0, 0, 0)
    camera.rotation.order = 'YXZ'
    camera.updateProjectionMatrix()

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({
      antialias: true
    })
    renderer.setSize(window.innerWidth, window.innerHeight)
    can!.appendChild(renderer.domElement)

    // 绘制模块
    const loader = new GLTFLoader()
    // @ts-expect-error 解决报错
    loader.load(scene_collision, gltf => {
      // @ts-expect-error 解决报错
      gltf.scene.traverse(child => {
        const texture = image.map(url =>
          new THREE.TextureLoader().load(url.url)
        )
        if (child.isMesh && child.name.startsWith('gallery')) {
          const index = parseInt(child.name.split('')[7]) // Assuming name ends with index
          if (!isNaN(index) && index < texture.length) {
            child.material.map = texture[index]
            child.material.needsUpdate = true
            child.userData.clickable = true
          }
        }
        if (child.isMesh) {
          child.castShadow = true
          child.receiveShadow = true
        }
      })

      // 初始化Raycaster
      const raycaster = new THREE.Raycaster()
      const mouse = new THREE.Vector2()

      // 添加点击事件监听器
      function onMouseClick(event: MouseEvent) {
        // 将鼠标位置归一化为设备坐标 [-1, 1]
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

        // 更新射线投射器
        raycaster.setFromCamera(mouse, camera)

        // 计算与所有子对象的交集
        const intersects = raycaster.intersectObjects(gltf.scene.children, true)

        if (intersects.length > 0) {
          const object = intersects[0].object
          if (object.userData.clickable) {
            const index = object.userData.name.split('')[7]
            // 在这里添加你想要执行的操作
            setTitle(image[index].title)
            setInfo(`你点击这幅画是: ${image[index].title}`) // 设置弹框信息
            setTimeout(() => {
              setInfo(null) // 1s 后关闭弹框
              setIntroduction(image[index].describe) // 设置弹框信息
            }, 1000) // 1s 后关闭弹框
          }
        }
      }

      window.addEventListener('click', onMouseClick, false)

      scene.add(gltf.scene)

      worldOctree.fromGraphNode(gltf.scene)
      const helper = new OctreeHelper(worldOctree)
      helper.visible = false
      // scene.add(helper)

      render()
    })

    // 加载桌子上的电脑
    // @ts-expect-error 解决报错
    loader.load(scene_desk_obj, gltf => {
      scene.add(gltf.scene)
    })

    // 添加画作

    // 添加光亮
    const light = new THREE.AmbientLight(0x404040, 100) // 柔和的白光
    scene.add(light)

    // render函数
    const render = () => {
      const dateTime = Math.min(0.5, clock.getDelta())
      handleControls(dateTime)
      updatePlayer(dateTime)
      renderer.render(scene, camera)
      requestAnimationFrame(render)
    }

    // 自适应视口
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
    })

    // mousedown 按下鼠标
    window.addEventListener('mousedown', () => {
      time = new Date().getTime()
      setTimeout(() => {
        if (new Date().getTime() - time! >= 200 && time !== null) {
          document.body.requestPointerLock()
        }
      }, 200)
    })

    // mousemove 鼠标移动
    window.addEventListener('mousemove', event => {
      if (document.pointerLockElement === document.body) {
        camera.rotation.y -= event.movementX / 500
        camera.rotation.x -= event.movementY / 500
      }
    })

    // mouseup 鼠标抬起
    window.addEventListener('mouseup', () => {
      document.exitPointerLock()
      time = null
    })

    // key
    window.addEventListener('keydown', event => {
      // @ts-expect-error 解决报错
      setKeyStates((keyStates[event.code] = true))
    })
    window.addEventListener('keyup', event => {
      // @ts-expect-error 解决报错
      setKeyStates((keyStates[event.code] = false))
    })

    // 键盘事件
    function handleControls(dateTime: number) {
      const speedDelat = dateTime * (player.onFloor ? 25 : 8)
      // @ts-expect-error 解决报错
      if (keyStates['KeyW']) {
        player.velocity.add(getForwardVector().multiplyScalar(speedDelat))
      }
      // @ts-expect-error 解决报错
      if (keyStates['KeyS']) {
        player.velocity.add(getForwardVector().multiplyScalar(-speedDelat))
      }
      // @ts-expect-error 解决报错
      if (keyStates['KeyA']) {
        player.velocity.add(getSideVector().multiplyScalar(-speedDelat))
      }
      // @ts-expect-error 解决报错
      if (keyStates['KeyD']) {
        player.velocity.add(getSideVector().multiplyScalar(speedDelat))
      }
      if (player.onFloor) {
        // @ts-expect-error 解决报错
        if (keyStates['Space']) {
          player.velocity.y = 15
        }
      }
    }
    // 前后移动事件
    function getForwardVector() {
      camera.getWorldDirection(player.direction)
      player.direction.y = 0
      player.direction.normalize()
      return player.direction
    }
    // 左右移动事件
    function getSideVector() {
      camera.getWorldDirection(player.direction)
      player.direction.y = 0
      player.direction.normalize()
      player.direction.cross(camera.up)
      return player.direction
    }

    // 玩家移动
    function updatePlayer(dateTime: number) {
      let damping = Math.exp(-4 * dateTime) - 1
      if (!player.onFloor) {
        player.velocity.y -= GRAVITY * dateTime
        damping *= 0.1
      }
      player.velocity.addScaledVector(player.velocity, damping)
      const deltaPosition = player.velocity.clone().multiplyScalar(dateTime)
      player.geomotry.translate(deltaPosition)
      playerCollisions()
      camera.position.copy(player.geomotry.end)
    }

    // 触地判断
    function playerCollisions() {
      const result = worldOctree.capsuleIntersect(player.geomotry)
      if (result) {
        player.onFloor = result.normal.y > 0
        if (player.onFloor) {
          player.velocity.addScaledVector(
            result.normal,
            -result.normal.dot(player.velocity)
          )
        }
        player.geomotry.translate(result.normal.multiplyScalar(result.depth))
      } else {
        player.onFloor = false
      }
    }
  }, [])

  const handleX = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    event.stopPropagation()
    setIntroduction(null)
  }

  const handleA = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    event.stopPropagation()
  }

  return (
    <div id="can" style={{ width: '100%', height: '100%' }}>
      {/* 进入页面自动播放音乐 */}
      <ReactPlayer
        style={{ display: 'none' }}
        url="http://zifan1998.oss-cn-beijing.aliyuncs.com/%E6%88%91%E8%AE%B0%E5%BE%97.m4a"
        playing={true} // 设置为true以便自动播放
        loop={true} // 是否循环播放，可根据需求设置
      />
      {info !== null && <div className="info">{info}</div>}
      {introduction !== null && (
        <div className="introduction" onClick={handleA}>
          {' '}
          <h4>{title}</h4> {introduction} <button onClick={handleX}>X</button>
        </div>
      )}
    </div>
  )
}

export default Index
